﻿#include <stdio.h>
#include "Emplyee.h"

double difference(int ival1, int ival2)
{
	return ival1 - ival2;
}

void main()
{
	Employee e;
	Manager	m;
	Programmer	p;

	// !!!!!!!!!!!!!!!implicit conversion
	int *i_p = 0;
	double r = difference(3, 2);

	// static_cast
	// 用法：static_cast < type-id > ( expression )
	// 说明：该运算符把expression转换为type-id类型，但没有运行时类型检查来保证转换的安全性。
	// 
	// 来源：为什么需要static_cast强制转换？
	//		情况1：void指针->其他类型指针
	//		情况2：改变通常的标准转换
	//		情况3：避免出现可能多种转换的歧义
	// 
	// 它主要有如下几种用法：
	//		用于类层次结构中基类和子类之间指针或引用的转换。进行上行转换（把子类的指针或引用转换成基类表示）是安全的；进行下行转换（把基类指针或引用转换成子类指针或引用）时，由于没有动态类型检查，所以是不安全的。
	//		用于基本数据类型之间的转换，如把int转换成char，把int转换成enum。这种转换的安全性也要开发人员来保证。
	//		把void指针转换成目标类型的指针(不安全!!)
	//		把任何类型的表达式转换成void类型。
	//
	//	注意：static_cast不能转换掉expression的const、volitale、或者__unaligned属性。
	int a = static_cast<int>('a');

	int * sc_i_p = static_cast<int*>(0);

	Employee* sc_e0 = static_cast<Employee*>(&e);
	Manager* sc_m0 = static_cast<Manager*>(&e);
	Programmer* sc_p0 = static_cast<Programmer*>(&e);

	Employee* sc_e1 = static_cast<Employee*>(&m);
	Manager* sc_m1 = static_cast<Manager*>(&m);
	//Programmer* sc_p1 = static_cast<Programmer*>(&m); //error C2440: 'static_cast' : cannot convert from 'Manager *' to 'Programmer *'

	Employee* sc_e2 = static_cast<Employee*>(&p);
	//Manager* sc_m2 = static_cast<Manager*>(&p);		//error C2440: 'static_cast' : cannot convert from 'Programmer *' to 'Manager *'
	Programmer* sc_p2 = static_cast<Programmer*>(&p);

	// !!!!!!!!!!!!!!! dynamic_cast
	//用法：dynamic_cast < type-id > ( expression )
	//
	//说明：该运算符把expression转换成type-id类型的对象。Type-id必须是类的指针、类的引用或者void *；如果type-id是类指针类型，那么expression也必须是一个指针，如果type-id是一个引用，那么expression也必须是一个引用。
	//
	//来源：为什么需要dynamic_cast强制转换？
	//简单的说，当无法使用virtual函数的时候
	//dynamic_cast主要用于类层次间的上行转换和下行转换，还可以用于类之间的交叉转换。
	Employee* dc_e0 = dynamic_cast<Employee*>(&e);
	Manager* dc_m0 = dynamic_cast<Manager*>(&e);
	Programmer* dc_p0 = dynamic_cast<Programmer*>(&e);

	Employee* dc_e1 = dynamic_cast<Employee*>(&m);
	Manager* dc_m1 = dynamic_cast<Manager*>(&m);
	Programmer* dc_p1 = dynamic_cast<Programmer*>(&m); 

	Employee* dc_e2 = dynamic_cast<Employee*>(&p);
	Manager* dc_m2 = dynamic_cast<Manager*>(&p);
	Programmer* dc_p2 = dynamic_cast<Programmer*>(&p);

	// !!!!!!!!!!!!!!! reinterpret_cast
	//用法：reinpreter_cast<type-id> (expression)
	//
	//说明：type-id必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数，也可以把一个整数转换成一个指针（先把一个指针转换成一个整数，在把该整数转换成原类型的指针，还可以得到原先的指针值）。
	Employee* rc_e0 = reinterpret_cast<Employee*>(&e);
	Manager* rc_m0 = reinterpret_cast<Manager*>(&e);
	Programmer* rc_p0 = reinterpret_cast<Programmer*>(&e);

	Employee* rc_e1 = reinterpret_cast<Employee*>(&m);
	Manager* rc_m1 = reinterpret_cast<Manager*>(&m);
	Programmer* rc_p1 = reinterpret_cast<Programmer*>(&m); 

	Employee* rc_e2 = reinterpret_cast<Employee*>(&p);
	Manager* rc_m2 = reinterpret_cast<Manager*>(&p);
	Programmer* rc_p2 = reinterpret_cast<Programmer*>(&p);

	Employee* sc_e9 = reinterpret_cast<Employee*>(0x12);
	int b = reinterpret_cast<int>(&p);
	
	// !!!!!!!!!!!!!!! const_cast
	//用法：const_cast<type_id> (expression)
	//
	//说明：该运算符用来修改类型的const或volatile属性。除了const 或volatile修饰之外， type_id和expression的类型是一样的。
	//
	//常量指针被转化成非常量指针，并且仍然指向原来的对象；常量引用被转换成非常量引用，并且仍然指向原来的对象；常量对象被转换成非常量对象。
	Employee* cc_e0 = const_cast<Employee*>(&e);
	//Manager* cc_m0 = const_cast<Manager*>(&e);		//error C2440: 'const_cast' : cannot convert from 'Employee *' to 'Manager *'
	//Programmer* cc_p0 = const_cast<Programmer*>(&e);	//error C2440: 'const_cast' : cannot convert from 'Employee *' to 'Programmer *'

	//Employee* cc_e1 = const_cast<Employee*>(&m);
	Manager* cc_m1 = const_cast<Manager*>(&m);
	//Programmer* cc_p1 = const_cast<Programmer*>(&m); 

	//Employee* cc_e2 = const_cast<Employee*>(&p);
	//Manager* cc_m2 = const_cast<Manager*>(&p);
	Programmer* cc_p2 = const_cast<Programmer*>(&p);

	const Employee cc_e3;
	//cc_e3.setAge(20);	//error C2662: 'Employee::setAge' : cannot convert 'this' pointer from 'const Employee' to 'Employee &'
	Employee cc_e4 = const_cast<Employee&>(cc_e3);
	cc_e4.setAge(20);

	Employee* cc_e5 = const_cast<Employee*>(&cc_e3);
	cc_e5->setAge(20);

	const Employee * const cc_e6 = new Employee;
	Employee cc_e7 = const_cast<Employee&>(*cc_e6);
	cc_e7.setAge(20);

	Employee* cc_e8 = const_cast<Employee*>(cc_e6);
	cc_e8->setAge(20);
	delete cc_e6;
}

